//
// System.Runtime.Serialization.SerializationInfo.cs
//
// Author:
//   Miguel de Icaza (miguel@ximian.com)
//   Duncan Mak (duncan@ximian.com)
//   Dietmar Maurer (dietmar@ximian.com)
//
// (C) Ximian, Inc.  http://www.ximian.com
//
//

//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

#ifndef SerializationInfo_h
#define SerializationInfo_h

// C# includes.
#include <Typedef.h>
#include <Defines.h>
#include <CSharpPropertyMethods.h>

// Riccsson includes.
#include <System/Collections/Generic/Dictionary.h>
#include <System/Collections/Generic/List.h>
#include <System/String.h>
#include <System/Char.h>
#include <System/Byte.h>
#include <System/SByte.h>
#include <System/Int16.h>
#include <System/UInt16.h>
#include <System/Int32.h>
#include <System/UInt32.h>
#include <System/Int64.h>
#include <System/UInt64.h>
#include <System/Boolean.h>
#include <System/Single.h>
#include <System/Double.h>
#include <System/Decimal.h>
#include <System/Runtime/Serialization/IFormatterConverter.h>
#include <System/Runtime/Serialization/FormatterConverter.h>
#include <System/Runtime/Serialization/SerializationEntry.h>
#include <System/Runtime/Serialization/SerializationInfoEnumerator.h>
#include <System/Runtime/Serialization/SerializationException.h>

namespace Riccsson
{
	namespace System
	{
		namespace Runtime
		{
			namespace Serialization
			{
	            class SerializationInfo sealed
	            {
		            //GC_PTR<System::Collections::Generic::Dictionary<GC_PTR<string>, GC_PTR<SerializationEntry>>> serialized; // TODO: Compiling error. Maybe for the GC_PTR<string>-key?
		            GC_PTR<System::Collections::Generic::List<GC_PTR<SerializationEntry>>> values;

		            GC_PTR<string> assemblyName; // the assembly being serialized
		            GC_PTR<string> fullTypeName; // the type being serialized.
            #if NET_4_0
		            Type objectType;
		            bool isAssemblyNameSetExplicit;
		            bool isFullTypeNameSetExplicit;
            #endif

		            GC_PTR<IFormatterConverter> converter;
		
		            /* used by the runtime */
		            private: SerializationInfo (Type* type)
		            {
			//			serialized = new System::Collections::Generic::Dictionary<GC_PTR<string>, GC_PTR<SerializationEntry>> ();
			//			values = new System::Collections::Generic::List<GC_PTR<SerializationEntry>> ();
			//
			//            assemblyName = type->Assembly->FullName;
			//            fullTypeName = type->FullName;
			//            converter = new FormatterConverter ();
            //#if NET_4_0
			//            objectType = type;
            //#endif
		            }
		
		            /* used by the runtime */
		            private: SerializationInfo (Type* type, Array<SerializationEntry>* data)
		            {
			//            int len = data->Length;
			//
			//            assemblyName = type->Assembly->FullName;
			//            fullTypeName = type->FullName;
			//            converter = new FormatterConverter ();
            //#if NET_4_0
			//            objectType = type;
            //#endif
			//
			//            for (int i = 0; i < len; i++) {
			//	            serialized->Add (data [i].Name, data [i]);
			//	            values->Add (data[i]);
			//            }
		            }

		            // Constructor
		            //[CLSCompliant (false)]
		            public: SerializationInfo (Type* type, IFormatterConverter* converter)
		            {
			//            if (type == null)
			//	            throw ArgumentNullException ("type", "Null argument");
			//
			//            if (converter == null)
			//	            throw ArgumentNullException ("converter", "Null argument");
			//
			//            this->converter = converter;
			//            assemblyName = type->Assembly.FullName;
			//            fullTypeName = type->FullName;
            //#if NET_4_0
			//            objectType = type;
            //#endif
		            }

		            // Properties
		            public: PROP3_GET(GC_PTR<string>, AssemblyName)
		            {
			            return assemblyName;
					}
					public: PROP3_SET(GC_PTR<string>, AssemblyName)
		            {
				        if (value == null)
					        throw ArgumentNullException ("Argument is null.");
				        assemblyName = value;
            #if NET_4_0
						isAssemblyNameSetExplicit = true;
            #endif
		            }
		
		            public: PROP3_GET(GC_PTR<string>, FullTypeName)
		            {
			            return fullTypeName;
					}
					public: PROP3_SET(GC_PTR<string>, FullTypeName)
		            {
				        if ( value == null)
					        throw ArgumentNullException ("Argument is null.");
				        fullTypeName = value;
            #if NET_4_0
						isFullTypeNameSetExplicit = true;
            #endif
		            }
		
		            public: PROP3_GET(int, MemberCount)
		            {
			            //return serialized->Count;
						throw;
		            }

            #if NET_4_0
		            public: PROP3_GET(bool, IsAssemblyNameSetExplicit)
					{
						return isAssemblyNameSetExplicit;
		            }

		            public: PROP3_GET(bool, IsFullTypeNameSetExplicit)
					{
						return isFullTypeNameSetExplicit;
		            }

		            public: PROP3_GET(GC_PTR<Type>, ObjectType)
					{
						return objectType;
		            }
            #endif

		            // Methods
		            public: void AddValue (string* name, object* value, Type* type)
		            {
			            //if (name == null)
				        //    throw ArgumentNullException ("name is null");
			            //if (type == null)
				        //    throw ArgumentNullException ("type is null");
						//
			            //if (serialized->ContainsKey (name))
				        //    throw SerializationException ("Value has been serialized already.");
						//
			            //SerializationEntry entry = new SerializationEntry (name, type, value);
						//
			            //serialized->Add (name, entry);
			            //values->Add (entry);
						throw;
		            }

		            public: GC_PTR<object> GetValue (string* name, Type* type)
		            {
			            //if (name == null)
				        //    throw ArgumentNullException ("name is null.");
			            //if (type == null)
				        //    throw ArgumentNullException ("type");
			            //if (!serialized->ContainsKey (name))
				        //    throw SerializationException ("No element named " + name + " could be found.");
						//
			            //SerializationEntry entry = serialized [name];
						//
			            //if (entry->Value != null && !type.IsInstanceOfType (entry->Value))
				        //    return converter-<Convert (entry->Value, type);
			            //else
				        //    return entry->Value;
						throw;
		            }

		            /*internal*/ bool HasKey (string* name)
		            {
			            //return serialized->ContainsKey (name);
						throw;
		            }
		
		            public: void SetType (Type* type)
		            {
			//            if (type == null)
			//	            throw ArgumentNullException ("type is null.");
			//
			//            fullTypeName = type->FullName;
			//            assemblyName = type->Assembly.FullName;
            //#if NET_4_0
			//            objectType = type;
			//            isAssemblyNameSetExplicit = false;
			//            isFullTypeNameSetExplicit = false;
            //#endif
						throw;
		            }

		            public: SerializationInfoEnumerator* GetEnumerator ()
		            {
			            //return new SerializationInfoEnumerator (values);
						throw;
		            }
		
		            public: void AddValue (string* name, Int16 value)
		            {
			            AddValue (name, &value, typeof (System::Int16));
		            }

		            //[CLSCompliant(false)]
		            public: void AddValue (string* name, UInt16 value)
		            {
			            AddValue (name, &value, typeof (System::UInt16));
		            }
		
		            public: void AddValue (string* name, Int32 value)
		            {
			            AddValue (name, &value, typeof (System::Int32));
		            }
		
		            public: void AddValue (string* name, Byte value)
		            {
			            AddValue (name, &value, typeof (System::Byte));
		            }
		
		            public: void AddValue (string* name, Boolean value)
		            {
			            AddValue (name, &value, typeof (System::Boolean));
		            }
	       
		            public: void AddValue (string* name, Char value)
		            {
			            AddValue (name, &value, typeof (System::Char));
		            }

		            //[CLSCompliant(false)]
		            public: void AddValue (string* name, SByte value)
		            {
			            AddValue (name, &value, typeof (System::SByte));
		            }
		
		            public: void AddValue (string* name, Double value)
		            {
			            AddValue (name, &value, typeof (System::Double));
		            }
		
		            public: void AddValue (string* name, Decimal value)
		            {
			            AddValue (name, &value, typeof (System::Decimal));
		            }
		
		            public: void AddValue (string* name, DateTime value)
		            {
			            AddValue (name, &value, typeof (System::DateTime));
		            }
		
		            public: void AddValue (string* name, Single value)
		            {
			            AddValue (name, &value, typeof (System::Single));
		            }

		            //[CLSCompliant(false)]
		            public: void AddValue (string* name, UInt32 value)
		            {
			            AddValue (name, &value, typeof (System::UInt32));
		            }
	       
		            public: void AddValue (string* name, Int64 value)
		            {
			            AddValue (name, &value, typeof (System::Int64));
		            }

		            //[CLSCompliant(false)]
		            public: void AddValue (string* name, UInt64 value)
		            {
			            AddValue (name, &value, typeof (System::UInt64));
		            }
		
		            public: void AddValue (string* name, object* value)
		            {
			            if (value == null)
				            AddValue (name, value, typeof (System::Object));
			            else
				            AddValue (name, value, value->GetType ());
		            }		
		
		            public: bool GetBoolean (string* name)
		            {
			            GC_PTR<object> value = GetValue (name, typeof (System::Boolean));
			            return converter->ToBoolean (value);
		            }
		
		            public: byte GetByte (string* name)
		            {
			            GC_PTR<object> value = GetValue (name, typeof (System::Byte));
			            return converter->ToByte (value);
		            }
		
		            public: char GetChar (string* name)
		            {
			            GC_PTR<object> value = GetValue (name, typeof (System::Char));
			            return converter->ToChar (value);
		            }

		            public: DateTime GetDateTime (string* name)
		            {
			            GC_PTR<object> value = GetValue (name, typeof (System::DateTime));
			            return converter->ToDateTime (value);
		            }
		
		            public: Decimal GetDecimal (string* name)
		            {
			            GC_PTR<object> value = GetValue (name, typeof (System::Decimal));
			            return converter->ToDecimal (value);
		            }
		
		            public: double GetDouble (string* name)
		            {
			            GC_PTR<object> value = GetValue (name, typeof (System::Double));
			            return converter->ToDouble (value);
		            }
						
		            public: short GetInt16 (string* name)
		            {
			            GC_PTR<object> value = GetValue (name, typeof (System::Int16));
			            return converter->ToInt16 (value);
		            }
		
		            public: int GetInt32 (string* name)
		            {
			            GC_PTR<object> value = GetValue (name, typeof (System::Int32));
			            return converter->ToInt32 (value);
		            }
	       
		            public: long long GetInt64 (string* name)
		            {
			            GC_PTR<object> value = GetValue (name, typeof (System::Int64));
			            return converter->ToInt64 (value);
		            }

		            //[CLSCompliant(false)]
		            public: sbyte GetSByte (string* name)
		            {
			            GC_PTR<object> value = GetValue (name, typeof (System::SByte));
			            return converter->ToSByte (value);
		            }
		
		            public: float GetSingle (string* name)
		            {
			            GC_PTR<object> value = GetValue (name, typeof (System::Single));
			            return converter->ToSingle (value);
		            }
		
		            public: GC_PTR<string> GetString (string* name)
		            {
			            GC_PTR<object> value = GetValue (name, typeof (System::String));
			            if (value == null) return null;
			            return converter->ToString (value);
		            }

		            //[CLSCompliant(false)]
		            public: UInt16 GetUInt16 (string* name)
		            {
			            GC_PTR<object> value = GetValue (name, typeof (System::UInt16));
			            return converter->ToUInt16 (value);
		            }
		
		            //[CLSCompliant(false)]
		            public: UInt32 GetUInt32 (string* name)
		            {
			            GC_PTR<object> value = GetValue (name, typeof (System::UInt32));
			            return converter->ToUInt32 (value);
		            }
		            //[CLSCompliant(false)]
		            public: UInt64 GetUInt64 (string* name)
		            {
			            GC_PTR<object> value = GetValue (name, typeof (System::UInt64));
			            return converter->ToUInt64 (value);
		            }

		            private: GC_PTR<Array<SerializationEntry>> get_entries ()
		            {
			            //GC_PTR<Array<SerializationEntry>> res = new Array<SerializationEntry>(this->MemberCount);
			            //int i = 0;
					    //
			            //for (int j = 0; j < this->this.Count; j++)
				        //    res [i++] = this->this[j];
					    //
			            //return res;
						throw;
		            }
	            };
            }
        }
    }
}

#endif